<?php
/* --------------------------------------------------------------
 StoreConfiguration.php 2020-10-19
 Gambio GmbH
 http://www.gambio.de
 Copyright (c) 2020 Gambio GmbH
 Released under the GNU General Public License (Version 2)
 [http://www.gnu.org/licenses/gpl-2.0.html]
 --------------------------------------------------------------
 */

declare(strict_types=1);

namespace Gambio\Admin\Modules\Configuration\App\Actions;

use Gambio\Admin\Modules\Customer\App\CustomerValidationService;
use Gambio\Core\Application\Http\AbstractAction;
use Gambio\Core\Application\Http\Request;
use Gambio\Core\Application\Http\Response;
use Gambio\Core\Configuration\Services\ConfigurationService;
use Throwable;
use Webmozart\Assert\Assert;

class StoreConfiguration extends AbstractAction
{
    private $configurationService;
    
    public function __construct(ConfigurationService $configurationService)
    {
        $this->configurationService = $configurationService;
    }
    
    public function handle(Request $request, Response $response): Response
    {
        try {
            $configurations = $request->getParsedBody()['configurations'] ?? [];
            Assert::isMap($configurations);
            
            $this->assertValidConfigurationCombination($configurations);
            
            foreach ($configurations as $key => $value) {
                if (is_array($value)) {
                    foreach ($value as $languageCode => $languageValue) {
                        $this->configurationService->saveLanguageDependent($key, $languageCode, $languageValue);
                    }
                } else {
                    if($key === CustomerValidationService::ACCOUNT_COMPANY_REQUIRED && in_array($value, ['true', 1, true])
                    && ($this->configurationService->find(CustomerValidationService::ACCOUNT_COMPANY)?->value() ?? "false") === "false") {
                        $this->configurationService->save(CustomerValidationService::ACCOUNT_COMPANY, 'true');
                    }
                    if($key === CustomerValidationService::ACCOUNT_COMPANY && in_array($value, ['false', 0, false])
                    && ($this->configurationService->find(CustomerValidationService::ACCOUNT_COMPANY_REQUIRED)?->value() ?? 'true') === 'true') {
                        $this->configurationService->save(CustomerValidationService::ACCOUNT_COMPANY_REQUIRED, 'false');
                    }
                    $this->configurationService->save($key, $value);
                }
            }
            
            $this->configurationService->saveBulk($configurations);
            
            return $response->withJson(['success' => true]);
        } catch (Throwable $exception) {
            return $response->withJson(['success' => false, 'error' => $exception->getMessage()], $exception->getCode());
        }
    }
    
    private function assertValidConfigurationCombination(array $configurations): void
    {
        $keyCompanyRequired = CustomerValidationService::ACCOUNT_COMPANY_REQUIRED;
        $keyNamesOptional   = CustomerValidationService::ACCOUNT_NAMES_OPTIONAL;
        
        $companyRequired = $configurations[$keyCompanyRequired] ?? $this->getBooleanConfiguration($keyCompanyRequired);
        $namesOptional   = $configurations[$keyNamesOptional]   ?? $this->getBooleanConfiguration($keyNamesOptional);
        
        $companyRequired = filter_var($companyRequired, FILTER_VALIDATE_BOOLEAN);
        $namesOptional   = filter_var($namesOptional, FILTER_VALIDATE_BOOLEAN);
        
        if (!$companyRequired && $namesOptional) {
            throw new \Exception(
                $this->textManager->getPhraseText('COMPANY_AND_NAMES_OPTIONAL_ERROR', 'configuration_validation'),
                422
            );
        }
    }
    
    private function getBooleanConfiguration(string $key): bool
    {
        $value = $this->configurationService->find($key)->value();
        return in_array($value, ['true', 1, true, '1'], true);
    }
}